<script setup lang="ts">
defineOptions({
  // eslint-disable-next-line vue/no-reserved-component-names
  name: "Song",
  inheritAttrs: false,
});

import { listAlbumOptions, listArtistOptions } from "@/api/application/artist";
import { getCateAllOptions } from "@/api/application/cate";
import {
  addSong,
  deleteSong,
  getSongForm,
  getTracklink,
  listSongs,
  updateSong,
} from "@/api/application/song";
import {
  RateFileInfo,
  SongForm,
  SongQuery,
  SongVO,
  TrackLinkVO,
} from "@/api/application/song/types";
import {
  getPresignedUrl,
  getPresignedUrlByName,
  pureUpload,
  uploadFile,
} from "@/api/minio";
// import { UploadFileDto } from "@/api/minio/type";
import SvgIcon from "@/components/SvgIcon/index.vue";
import { AudioRateEnum } from "@/enums/audio.enum";
import {
  FFmpegClass,
  MimeEnum,
  fileToBase64,
  getVideoPosterInfo,
} from "@/utils/ffmpeg";

import { deleteById, deleteByIds } from "@/api/file";
import { UploadFileDto, UploadVideoForm } from "@/api/minio/type";
import { video_mime_type } from "@/const";
import { useAudioStore } from "@/store/modules/audio";
import { checkMediaFile } from "@/utils";
import {
  Close,
  Delete,
  InfoFilled,
  Plus,
  UploadFilled,
  VideoPlay,
} from "@element-plus/icons-vue";
import { FFmpeg } from "@ffmpeg/ffmpeg";
import axios, { AxiosProgressEvent } from "axios";
import {
  ElLoading,
  UploadFile,
  UploadFiles,
  UploadInstance,
  UploadProps,
  UploadRawFile,
  genFileId,
} from "element-plus";
import { OptionType } from "element-plus/es/components/select-v2/src/select.types";
import { storeToRefs } from "pinia";
import { onMounted, reactive, ref } from "vue";
const store = useAudioStore();
const { currentTime, currentTimeStr, lrcData, lrcText } = storeToRefs(store);
let ffmpeg = ref<FFmpeg>();
let audio = ref<HTMLAudioElement>();
let lrcType = ref<boolean>(true);

const queryFormRef = ref(ElForm);
const songFormRef = ref(ElForm);
const queryParams = reactive<SongQuery>({
  pageNum: 1,
  pageSize: 10,
});
const loading = ref(false);
const filterLoading = ref(false);
const dialog = reactive({
  title: "",
  visible: false,
});

const uploadDialog = reactive({
  title: "",
  visible: false,
  active: 1,
});
const lrcDialog = reactive({
  visible: false,
  title: "填写歌词",
});
const lrcFormData = reactive({
  audioUrl: "",
  album: "",
  title: "",
  editor: "",
  artist: "",
});

watch(
  () => lrcData.value.title,
  (nv, ov) => {
    if (nv) {
      formData.title = nv;
    }
  }
);

const validateVideo = (rule: any, value: any, callback: any) => {
  console.log(rule, value);
  if (!tmpVideo) {
    callback(new Error("请上传视频"));
  } else {
    if (!tmpVideo?.id) {
      // const { url, objectName } =  getPresignedUrlByName(tmpVideo!.raw!.name, false)
      //获取上传链接
      getPresignedUrlByName(tmpVideo!.raw!.name, false)
        .then(async ({ url, objectName }) => {
          //上传
          let loading = null;
          try {
            const { imageData } = await getVideoPosterInfo(tmpVideo!.url!);
            // const { imageData } = await getVideoPosterInfo("http://127.0.0.1:9000/public/%E3%80%8EMV%E3%80%8F%E6%AF%9B%E4%B8%8D%E6%98%93Mao%20Buyi%20-%20%E5%80%9F%20%E5%AE%98%E6%96%B9%E9%AB%98%E7%95%AB%E8%B3%AA%20Official%20HD%20MV-%281080p%29.mp4")
            const imageName =
              tmpVideo!.raw!.name.slice(
                0,
                tmpVideo!.raw!.name.lastIndexOf(".")
              ) + ".png";

            const image = await getPresignedUrlByName(imageName);
            await pureUpload(
              image.url,
              new File([imageData!], imageName, { type: imageData!.type }),
              (loaded, total) => {
                console.log("上传进度", loaded, total);
              }
            );
            await pureUpload(url, tmpVideo.raw!, (loaded, total) => {
              console.log("上传进度", loaded, total);
              loading = ElLoading.service({
                lock: true,
                text: `${((loaded / total) * 100).toFixed(0)}%`,
                background: "rgba(0, 0, 0, 0.7)",
              });
            });
            tmpVideo.objectName = objectName;
            tmpVideo.url = "";
            tmpVideo.poster = image.url.split("?").at(0);
            formData.video = tmpVideo!;
            callback();
            loading!.close();
          } catch (error: any) {
            callback(new Error(error));
            loading!.close();
          }

          // uploadVideo(tmpVideo.raw!)
          //   .then(({ id, url }) => {
          //     tmpVideo.id = id;
          //     tmpVideo.url = "";
          //     formData.video = tmpVideo!;
          //     callback();
          //   })
          //   .catch((err) => {
          //     callback(new Error(err));
          //   });
        })
        .catch((err) => {
          callback(new Error(err));
        });
    } else {
      callback();
    }
  }
};

const upload = ref<UploadInstance>();
const previewVideo = ref<HTMLVideoElement>();
const playSong = ref<TrackLinkVO>();
const uploadVideoRef = ref<UploadInstance>();
const songList = ref<SongVO[]>([]);
const artistOptions = ref<OptionType[]>([]);
const albumOptions = ref<OptionType[]>([]);
const cateOptions = ref<OptionType[]>([]);
const uploadUrl = ref<string>();

const formData = reactive<SongForm>({
  sort: 0,
  title: "",
  genre: undefined,
  isActive: true,
  artistIds: [],
  introduce: "",
  downTime: new Date(),
  pushTime: new Date(),
  lang: "",
  lyric: "",
  isVip: false,
  pic: [],
  releaseDate: new Date(),
  rateList: [],
  rateFileInfos: [],
  albumIds: [],
});

const tmpRateFileInfos = ref<RateFileInfo[]>([]);
const tmpPic = ref<Array<UploadFileDto>>([]);
const tmpVideo = reactive<UploadVideoForm>({
  id: "",
  url: "",
  name: "",
  status: "ready",
  uid: 0,
  poster: "",
  size: 0,
  lastModified: 0,
  type: "",
  webkitRelativePath: "",
});
const removeIds = ref([]); // 删除歌曲ID集合 用于批量删除
const rules = reactive({
  video: [{ required: true, validator: validateVideo, trigger: "submit" }],
  title: [{ required: true, message: "请选择歌单", trigger: "blur" }],
  songName: [{ required: true, message: "请输入歌曲名称", trigger: "blur" }],
});
const total = ref(0); // 数据总数
// 选择表格的行歌曲ID
const selectedRowSongId = ref<number | undefined>();

//音频数据列表
const audioFileList = ref<any[]>([]);

const uploadMvUrl = computed(
  () => import.meta.env.VITE_APP_BASE_API + "/api/v1/minio"
);
const videoMimeType = computed(() => Object.keys(video_mime_type).join(","));

const active = computed(() => {
  const allReady =
    tmpRateFileInfos.value.length > 0 &&
    (tmpRateFileInfos.value.every((rateFile) => {
      if (rateFile.rate == AudioRateEnum.UNDAMAGED) {
        return true;
      }
      return rateFile.status === "ready" || rateFile.status === "transformed";
    }) ||
      tmpRateFileInfos.value.every((rateFile) => rateFile.status));
  const allTransformed =
    tmpRateFileInfos.value.length > 0 &&
    tmpRateFileInfos.value.every((rateFile) => {
      if (rateFile.rate == AudioRateEnum.UNDAMAGED) {
        return true;
      }
      return rateFile.status === "transformed";
    });
  const allUpload =
    tmpRateFileInfos.value.length > 0 &&
    tmpRateFileInfos.value.every((rateFile) => rateFile.status === "success");

  console.log(allTransformed, allReady, allUpload);

  if (allUpload && allTransformed && allReady) {
    return 3;
  } else if (!allUpload && allTransformed && allReady) {
    return 2;
  } else if (!allUpload && !allTransformed && allReady) {
    return 1;
  } else {
    return;
  }
});

/**
 * 查询
 */
async function handleQuery() {
  // 重置父组件
  loading.value = true;
  try {
    const data = await listSongs(queryParams);

    // songList.value = data;

    songList.value = data.list;
    total.value = data.total;
  } catch (error) {
  } finally {
    loading.value = false;
  }
}

/** 重置查询 */
function resetQuery() {
  queryFormRef.value.resetFields();
  handleQuery();
}

/**行点击事件 */
function onRowClick(row: SongVO) {
  selectedRowSongId.value = row.id;
}

/** 行选中 */
function handleSelectionChange(selection: any) {
  removeIds.value = selection.map((item: any) => item.id);
}

/**
 * 打开表单弹窗
 *
 * @param parentId 父歌曲ID
 * @param songId 歌曲ID
 */
async function openDialog(parentId?: number, songId?: number) {
  cateOptions.value = await getCateAllOptions(2);
  // cateOptions.value = data

  dialog.visible = true;
  if (songId) {
    dialog.title = "编辑歌曲";
    const data = await getSongForm(songId);
    Object.assign(formData, data);
    lrcData.value.lrcText = data.lyric;
    lrcData.value.title = data.title;
    lrcData.value.artist =
      data.artistList?.map((art) => art.name).join(",") ?? "";
    formData.artistIds = data.artistIds;
    artistOptions.value =
      data?.artistList?.map<any>((artist) => ({
        label: artist.name,
        value: artist.id,
      })) ?? [];

    albumOptions.value = data?.album
      ? [
          {
            label: data?.album.title,
            value: data?.album.id,
          },
        ]
      : [];
    formData.rateList = data.rateFileInfos.map<AudioRateEnum>(
      (rateFile) => rateFile.rate
    );
    tmpRateFileInfos.value = [...formData.rateFileInfos];
    tmpPic.value = [...formData.pic];
    tmpVideo.id = formData.video?.id;
    tmpVideo.url = formData.video?.url;
    tmpVideo.poster = formData.video?.poster ?? "";
    console.log(formData, data);
  } else {
    dialog.title = "新增歌曲";
  }
}

/** 歌曲保存提交 */
function submitForm() {
  songFormRef.value.validate(async (isValid: boolean) => {
    if (isValid) {
      try {
        if (tmpPic.value.length > 0) {
          formData.pic = tmpPic.value;
        }

        let pic = formData.pic[0];

        if (pic && pic.url?.startsWith(import.meta.env.VITE_MEDIA_BLOB_BASE)) {
          pic.isPublic = true;
          let avatarPicForm = await uploadFile(pic, (progress, total) => {
            console.log(progress, total);
          });

          formData.pic[0].url = avatarPicForm!.url!;
          formData.pic[0].id = avatarPicForm!.id!;
          formData.pic[0].percentage = 100;
          formData.pic[0].isPublic = true;
        }

        if (tmpVideo?.url) {
          formData!.video!.url = tmpVideo.url;
          formData!.video!.id = tmpVideo.id;
        }

        if (formData.id) {
          await updateSong(formData.id, formData);
        } else {
          await addSong(formData);
        }

        ElMessage.success(`${formData.id ? "修改" : "新增"}成功`);

        closeDialog();
        handleQuery();
      } catch (error) {
        throw error;
      } finally {
      }
    }
  });
}

/** 删除歌曲 */
function handleDelete(id?: number) {
  const ids = id ?? removeIds.value;
  if (!ids) {
    ElMessage.warning("请勾选删除项");
    return false;
  }

  ElMessageBox.confirm("确认删除已选中的数据项?", "警告", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  })
    .then(async () => {
      await deleteSong(ids);
      ElMessage.success("删除成功");
      handleQuery();
    })
    .catch(() => ElMessage.info("已取消删除"));
}

/**
 * 筛选歌手名称
 * @param query
 */
const filterArtist = async (query: string) => {
  if (query !== "") {
    filterLoading.value = true;
    artistOptions.value = await listArtistOptions({
      keywords: query,
      pageNum: 1,
      pageSize: 10,
    });
    filterLoading.value = false;
  } else {
    artistOptions.value = [];
  }
};

/**
 * 筛选专辑名称
 * @param query
 */
const filterAlbum = async (query: string) => {
  if (query !== "") {
    filterLoading.value = true;
    albumOptions.value = await listAlbumOptions({
      alubmName: query,
      pageNum: 1,
      pageSize: 10,
    });
    filterLoading.value = false;
  } else {
    albumOptions.value.length > 0 ? albumOptions : (albumOptions.value = []);
  }
};

/**
 * 播放视频
 */
function playVideo() {}

/** 关闭弹窗 */
function closeDialog() {
  dialog.visible = false;
  resetForm();
}

/** 重置表单 */
function resetForm() {
  songFormRef.value.resetFields();
  songFormRef.value.clearValidate();
  formData.pic = [];

  formData.rateFileInfos = [];
  formData.rateList = [];
  tmpPic.value = [];
  tmpRateFileInfos.value = [];
  formData.id = undefined;
  formData.sort = 1;
}

const beforeImageUpload: UploadProps["beforeUpload"] = async (
  rawFile: UploadRawFile
) => {
  // if (rawFile.type !== "image/jpeg") {
  //   ElMessage.error("Avatar picture must be JPG format!");
  //   return false;
  // } else if (rawFile.size / 1024 / 1024 > 2) {
  //   ElMessage.error("Avatar picture size can not exceed 2MB!");
  //   return false;
  // }

  // const o = Object.assign({}, { ...rawFile });
  // const form: UploadFileDto = {
  //   name: "",
  //   uid: 0,
  //   status: "ready",
  //   size: 0,
  //   lastModified: 0,
  //   type: "",
  //   webkitRelativePath: "",
  //   pic: undefined,
  // };
  // form.uid = rawFile.uid;
  // form.lastModified = rawFile.lastModified;
  // form.size = rawFile.size;
  // form.type = rawFile.type;
  // form.name = rawFile.name;

  // const url = await getPresignedUrl(form);

  // uploadUrl.value = url;
  return true;
};

/**
 * 选择视频
 * @param uploadFile
 */
const videoFileChange: UploadProps["onChange"] = async (
  uploadFile: UploadFile
) => {
  // new Blob([uploadFile!.raw!.buffer], { type: 'audio/mpeg' })
  const result = await checkMediaFile(uploadFile!.raw! as File);
  console.log(result);

  const [general, video, audio] = result.media.track;

  const { Duration, Width, Height } = video;
  const { url, filename } = await fileToBase64(
    uploadFile!.raw!,
    ({ loaded, total }: ProgressEvent) => {
      console.log(((loaded / total) * 100).toFixed(2));
    }
  );

  let videoDto: UploadFileDto = uploadFile as UploadFileDto;
  // form.id = id;
  // form.url = URL.createObjectURL(uploadFile!.raw!);
  tmpVideo.raw = uploadFile!.raw!;
  tmpVideo.url = url;
  tmpVideo.width = Width;
  tmpVideo.height = Height;
  tmpVideo.duration = Duration;
};
/**
 * 选择头像
 * @param uploadFile
 */
const avatarFileChange: UploadProps["onChange"] = async (
  uploadFile: UploadFile
) => {
  uploadFile.url = URL.createObjectURL(uploadFile.raw!);

  console.log(uploadFile.url);

  let form: UploadFileDto = uploadFile as UploadFileDto;

  // formData.pic.with(0, { ...form, isPublic: true });
  let avatar: UploadFileDto = {
    name: "",
    uid: 0,
    status: "ready",
    size: 0,
    lastModified: 0,
    type: "",
    webkitRelativePath: "",
    isPublic: true,
  };

  // formData.pic.push(avatar);
  tmpPic.value.push(avatar);
  console.log(formData.pic, tmpPic.value);
};

//删除头像
async function deletePic() {
  const picID = formData.pic[0]?.id ?? "";
  const tmpPicId = tmpPic.value.at(0)?.id ?? "";

  try {
    if (tmpPicId && tmpPicId != picID) {
      await deleteById(tmpPicId);
      ElMessage.success("删除头像成功");
    } else if (tmpPicId && tmpPicId == picID) {
      formData.pic = [];
    }
    tmpPic.value = [];
  } catch (error) {
    ElMessage.error("删除失败");
  } finally {
  }
}

const handleAvatarSuccess: UploadProps["onSuccess"] = async (
  response: any,
  uploadFile: UploadFile,
  uploadFiles: UploadFiles
) => {
  // const remoteUrl = response.config.url.split("?")[0];
  // let form: UploadFileDto = uploadFile as UploadFileDto;
  // form.url = remoteUrl;
  // form.isPublic = true;
  // await updateMinioFile(form);
  // formData.pic = [form];
};

/**
 * 确定上传音频文件
 */
const handleAudioSubmit = () => {
  formData.rateFileInfos = tmpRateFileInfos.value;
  uploadDialog.visible = false;
  unmountAudioPlayer();
};

/**
 * 取消上传音频文件
 */
const closeUploadDialog = async () => {
  try {
    await deleteTmpAudioFile();
    tmpRateFileInfos.value = formData.rateFileInfos;
    uploadDialog.visible = false;
    unmountAudioPlayer();
  } catch (error) {
    console.error(error);
    ElMessage.error("删除失败");
  }
};

/**
 * 音频上传文件限制触发钩子
 * @param files
 */
const handleExceed: UploadProps["onExceed"] = (files) => {
  upload.value!.clearFiles();
  const file = files[0] as UploadRawFile;
  file.uid = genFileId();
  upload.value!.handleStart(file);
};

const submitUploadMv = () => {
  uploadVideoRef.value!.submit();
};

/**
 * 手动上传音频文件
 */
const submitUpload = async () => {
  // upload.value!.submit();

  // const { rateFileInfos } = formData;

  if (tmpRateFileInfos.value.length === 0) {
    ElMessage.error("请选择文件");
  }

  const querys = tmpRateFileInfos.value.map<Promise<any>>((rateFile) => {
    const params: UploadFileDto = {
      name: "",
      uid: 0,
      status: "ready",
      size: 0,
      lastModified: 0,
      type: "",
      webkitRelativePath: "",
    };
    params.name = rateFile?.name!;
    const { name, blob, mimeType, file } = rateFile;
    // return getPresignedUrl({ name })
    rateFile.file;
    rateFile!.file!.name! = rateFile!.name!;

    return (async () => {
      let filedesc = rateFile!.file! as UploadFileDto;
      filedesc.percentage = rateFile.file?.percentage;
      filedesc.size = rateFile.file?.raw?.size ?? 0;
      filedesc.type = rateFile?.mimeType!;
      filedesc.lastModified = rateFile.file?.raw?.lastModified!;
      let file = rateFile.file?.raw;

      const { url, fileId } = await getPresignedUrl(filedesc);
      rateFile.fileId = fileId;
      return await axios.put(
        url,
        rateFile.rate == AudioRateEnum.UNDAMAGED ? file : blob,
        {
          headers: { "Content-Type": mimeType },
          onUploadProgress: (e: AxiosProgressEvent) => {
            console.log("上传进度: " + name, e.loaded);

            rateFile.percentage = +((e.loaded / e!.total!) * 100).toFixed(0);

            if (rateFile.percentage == 100) {
              rateFile.status = "success";
            }
          },
        }
      );
    })();
  });

  const data = await Promise.all(querys);
  console.log("请求数据", tmpRateFileInfos);
};

/**
 * 选择音频
 * @param uploadFile
 */
const audioFileChange: UploadProps["onChange"] = async (
  uploadFile: UploadFile
) => {
  tmpRateFileInfos.value = formData.rateList.map((rate) => {
    return {
      name: `${rate}_${uploadFile.name}`,
      rate: rate,
      status: "ready",
      size: uploadFile.size!,
      duration: 0,
      uploadProgress: 0,
      format: "mp3",
      isFull: true,
      mimeType:
        rate == AudioRateEnum.UNDAMAGED ? uploadFile.raw?.type : MimeEnum.mp3,
      fileId: "",
      percentage: 0,
      transformProgress: rate == AudioRateEnum.UNDAMAGED ? 100 : 0,
      file: uploadFile,
    };
  });
  if (formData.isVip) {
    tmpRateFileInfos.value.push({
      name: `cut_${uploadFile.name}`,
      rate: AudioRateEnum.LOSSY,
      percentage: 0,
      transformProgress: 0,
      status: "ready",
      size: 0,
      duration: 30,
      format: "mp3",
      isFull: false,
      mimeType: MimeEnum.mp3,
      fileId: "",
      file: uploadFile,
    });
  }
  // formData.rateFileInfos = tmpRateFileInfos
  console.log(formData.rateFileInfos, tmpRateFileInfos);

  uploadFile.url = URL.createObjectURL(uploadFile.raw!);
};

//转码
const transformAudio = async () => {
  for await (const rateFile of tmpRateFileInfos.value) {
    if (rateFile.rate == AudioRateEnum.UNDAMAGED) {
      rateFile.status = "transformed";
      continue;
    }
    const blob = await FFmpegClass.operateAudioFile(
      rateFile!.file!.raw!,
      "mp3",
      rateFile.rate,
      (progress: number, time: number) => {
        console.log(progress, time, tmpRateFileInfos.value);
        rateFile.transformProgress = +progress.toFixed(0);
        if (rateFile.transformProgress === 100) {
          rateFile.status = "transformed";
        }
      }
    );
    rateFile.blob = blob;
    rateFile.size = blob.size;
  }
};

const confirmDelPic = async () => {
  console.log("删除");
  await deletePic();
};
const cancelDelPic = () => {};

/**
 *
 * 确认删除文件列表
 */
const confirmDelRateFiles = async () => {
  console.log("删除-音频");
  // const songId = formData.id;
  // const rateIds = formData.rateFileInfos.map((rateFile) => rateFile!.id!);
  // await deleteRateFiles(songId!, rateIds!);

  try {
    await deleteTmpAudioFile();
  } catch (error) {
    console.error(error);
    ElMessage.error("删除失败");
  }
};

/**
 * 删除临时文件列表
 */
const deleteTmpAudioFile = async () => {
  if (tmpRateFileInfos.value.length > 0) {
    // await deleteByIds(tmpRateFileInfos.value.map(rateFile => rateFile.fileId))
    for await (const tmpRatefile of tmpRateFileInfos.value) {
      if (
        !formData.rateFileInfos.find(
          (rateFile) => rateFile.fileId == tmpRatefile.fileId
        ) &&
        tmpRatefile.fileId
      ) {
        await deleteById(tmpRatefile.fileId);
      }
    }
  }

  tmpRateFileInfos.value = [];
};

/**
 * 删除临时图片列表
 */
const deleteTmpPic = async () => {
  if (tmpPic.value.length > 0) {
    await deleteByIds(
      tmpRateFileInfos.value.map((rateFile) => rateFile.fileId)
    );
    // for await (const tmpRatefile of tmpRateFileInfos.value) {
    //   if (!formData.rateFileInfos.find(rateFile => rateFile.fileId == tmpRatefile.fileId) && tmpRatefile.fileId) {
    //     await deleteById(tmpRatefile.fileId)
    //   }
    // }
  }

  tmpRateFileInfos.value = [];
};

const play = async () => {
  const song: TrackLinkVO = await getTracklink({ id: formData.id! });

  playSong.value = song;

  console.log(playSong);
};

/**
 * 清空视频
 */
const clearVideoTmp = () => {
  formData.video = undefined;
  tmpVideo.poster = "";
  tmpVideo.url = "";
  tmpVideo.id = "";
};

function songCanplay(e: Event) {
  console.log("canplay");
  audio.value?.play();
}

function unmountAudioPlayer() {
  if (audio) {
    audio.value?.pause();
    audio.value?.removeAttribute("src");
    audio.value?.load();
    audio.value = undefined;
  }
}

const changeAudioFile: UploadProps["onChange"] = async (
  rawFile: UploadFile
) => {
  const result = await checkMediaFile(rawFile.raw as File);
  const { Album, Title, Performer, Track, Duration, Format, FileSize } =
    result.media.track.at(0);
  formData.rateFileInfos.map((rateFile) => ({
    ...rateFile,
    duration: Duration,
  }));
  lrcData.value.title = typeof Title === "string" ? Title : "未知歌曲";
  lrcData.value.album = typeof Album === "string" ? Album : "未知专辑";
  lrcData.value.artist = typeof Performer === "string" ? Performer : "未知歌手";
  lrcData.value.audioUrl = URL.createObjectURL(rawFile.raw!);
};

/**
 * 歌词弹框确定按钮
 */
const handleLrcSubmit = () => {
  formData.lyric = lrcText.value;
  lrcDialog.visible = false;
  lrcData.value.closeAudio = true;
};
/**
 * 歌词弹框取消按钮
 */
const closeLrcDialog = () => {
  lrcDialog.visible = false;
  lrcData.value.closeAudio = true;
};

onMounted(() => {
  handleQuery();
  // MediaInfoFactory().then(() => {
  //   console.log('Loaded');
  // });
});
</script>

<template>
  <div class="app-container">
    <div class="search-container">
      <el-form ref="queryFormRef" :model="queryParams" :inline="true">
        <el-form-item label="关键字" prop="songName">
          <el-input
            v-model="queryParams.songName"
            placeholder="歌曲名称"
            clearable
            @keyup.enter="handleQuery"
          />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="handleQuery"
            ><template #icon><i-ep-search /></template>搜索</el-button
          >
          <el-button @click="resetQuery">
            <template #icon><i-ep-refresh /></template>
            重置</el-button
          >
        </el-form-item>
      </el-form>
    </div>

    <el-card shadow="never" class="table-container">
      <template #header>
        <el-button
          v-hasPerm="['sys:song:create']"
          type="success"
          @click="openDialog(0)"
        >
          <template #icon><i-ep-plus /></template>
          新增</el-button
        >
        <el-button
          v-hasPerm="['sys:song:delete']"
          type="danger"
          :disabled="removeIds.length === 0"
          @click="handleDelete()"
          ><i-ep-delete />删除</el-button
        >
      </template>

      <el-table
        v-loading="loading"
        :data="songList"
        @selection-change="handleSelectionChange"
      >
        <el-table-column type="selection" width="50" />
        <el-table-column label="id" align="left" width="50" prop="id" />

        <el-table-column label="歌曲名称" min-width="150">
          <template #default="scope">
            <svg-icon :icon-class="scope.row.icon" />
            {{ scope.row.title }}
          </template>
        </el-table-column>
        <el-table-column label="标签" min-width="150">
          <template #default="scope">
            <el-tag type="info">
              {{ scope.row.genre?.at(0)?.categoryName ?? "" }}</el-tag
            >
          </template>
        </el-table-column>
        <el-table-column label="歌手" min-width="150">
          <template #default="scope">
            {{
              scope.row.artistList.map((artist: any) => artist.name).join(",")
            }}
          </template>
        </el-table-column>
        <el-table-column label="语言" align="left" width="150" prop="lang" />

        <el-table-column label="状态" align="center" width="200">
          <template #default="scope">
            <el-tag v-if="scope.row.isActive" type="success">正常</el-tag>
            <el-tag v-else type="info">禁用</el-tag>
          </template>
        </el-table-column>

        <el-table-column label="排序" align="center" width="300" prop="sort" />
        <el-table-column
          label="创建时间"
          align="left"
          width="200"
          prop="createTime"
        />
        <el-table-column
          label="发行时间"
          align="left"
          width="200"
          prop="releaseDate"
        />
        <el-table-column
          label="上架时间"
          align="left"
          width="200"
          prop="pushTime"
        />
        <el-table-column
          label="下架时间"
          align="left"
          width="200"
          prop="downTime"
        />
        <el-table-column fixed="right" align="center" label="操作" width="220">
          <template #default="scope">
            <el-button
              v-if="scope.row.parentId === 0"
              v-hasPerm="['sys:song:create']"
              type="primary"
              link
              size="small"
              @click.stop="openDialog(scope.row.id)"
            >
              <i-ep-plus />新增
            </el-button>

            <el-button
              v-hasPerm="['sys:song:update']"
              type="primary"
              link
              size="small"
              @click.stop="openDialog(undefined, scope.row.id)"
            >
              <i-ep-edit />编辑
            </el-button>
            <el-button
              v-hasPerm="['sys:song:delete']"
              type="primary"
              link
              size="small"
              @click.stop="handleDelete(scope.row.id)"
              ><i-ep-delete />
              删除
            </el-button>
          </template>
        </el-table-column>
      </el-table>

      <template #footer>
        <pagination
          v-if="total > 0"
          v-model:total="total"
          v-model:page="queryParams.pageNum"
          v-model:limit="queryParams.pageSize"
          @pagination="handleQuery"
        />
      </template>
    </el-card>

    <!-- 添加歌曲 -->
    <el-dialog
      v-model="dialog.visible"
      :title="dialog.title"
      destroy-on-close
      append-to-body
      width="800px"
      @close="closeDialog"
      :draggable="true"
      top="5vh"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
    >
      <el-form
        ref="songFormRef"
        :model="formData"
        :rules="rules"
        label-width="100px"
      >
        <el-form-item label="关联歌手" prop="artistIds">
          <el-select-v2
            v-model="formData.artistIds"
            style="width: 240px"
            multiple
            filterable
            remote
            :remote-method="filterArtist"
            clearable
            :options="artistOptions"
            :loading="filterLoading"
            placeholder="选择歌手"
          />
        </el-form-item>

        <el-form-item label="关联专辑" prop="albumIds">
          <el-select-v2
            :multiple-limit="1"
            v-model="formData.albumIds"
            style="width: 240px"
            multiple
            filterable
            remote
            :remote-method="filterAlbum"
            clearable
            :options="albumOptions"
            :loading="filterLoading"
            placeholder="选择专辑"
          />
        </el-form-item>

        <el-form-item required label="歌曲名称" prop="title">
          <el-input v-model="formData.title" placeholder="请输入歌曲名称" />
        </el-form-item>

        <el-form-item label="封面" prop="pic">
          <div
            v-show="tmpPic[0] && tmpPic[0].url"
            class="avatar-delete-wrapper"
          >
            <img crossOrigin="anonymous" :src="tmpPic[0]?.url" class="avatar" />
            <span class="avatar-cover-wrapper">
              <el-icon class="avatar-icon avatar-zoomin-icon">
                <Close />
              </el-icon>

              <el-popconfirm
                placement="right"
                confirm-button-text="是"
                cancel-button-text="否"
                :icon="InfoFilled"
                icon-color="#626AEF"
                title="你确定要删除头像"
                @confirm="confirmDelPic"
                @cancel="cancelDelPic"
              >
                <template #reference>
                  <el-icon class="avatar-icon avatar-delete-icon">
                    <Delete />
                  </el-icon>
                </template>
              </el-popconfirm>
            </span>
          </div>
          <el-upload
            ref="uploadAvatarRef"
            v-show="!(tmpPic[0] && tmpPic[0].url)"
            class="avatar-uploader"
            v-model:file-list="tmpPic"
            method="put"
            accept="image/bmp,image/gif,image/vnd.microsoft.icon,image/jpeg,image/webp"
            :show-file-list="false"
            :auto-upload="false"
            :on-success="handleAvatarSuccess"
            :on-change="avatarFileChange"
            :before-upload="beforeImageUpload"
          >
            <el-icon class="avatar-uploader-icon">
              <Plus />
            </el-icon>
          </el-upload>
        </el-form-item>

        <el-form-item label="VIP" prop="isActive">
          <el-switch v-model="formData.isVip" />
        </el-form-item>

        <el-form-item label="音质" prop="rateList">
          <el-space direction="horizontal" alignment="start" :size="30">
            <el-checkbox-group v-model="formData.rateList">
              <el-checkbox label="3000">无损</el-checkbox>
              <el-checkbox label="320">高质</el-checkbox>
              <el-checkbox label="128">标准</el-checkbox>
              <el-checkbox label="64">全损</el-checkbox>
            </el-checkbox-group>
            <el-button
              type="primary"
              :icon="UploadFilled"
              circle
              :disabled="formData.rateList.length === 0"
              @click="uploadDialog.visible = true"
            />
          </el-space>
        </el-form-item>

        <el-form-item label="视频" prop="video">
          <el-upload
            v-if="!(tmpVideo && tmpVideo.url)"
            ref="uploadVideoRef"
            class="upload-video"
            :accept="videoMimeType"
            :auto-upload="false"
            :on-change="videoFileChange"
            :show-file-list="false"
          >
            <template #trigger>
              <el-button class="upload-btn">上传视频</el-button>
            </template>
          </el-upload>
          <div class="upload-video" v-else>
            <el-icon
              class="avatar-icon avatar-delete-icon delete-video-icon"
              @click="clearVideoTmp"
            >
              <Delete />
            </el-icon>
            <!-- <vue3-video-player
              :poster="tmpVideo!.poster!"
              crossorigin="anonymous"
              class="upload-video"
              @play="playVideo"
              :src="tmpVideo!.url!"
            ></vue3-video-player> -->
            <video
              ref="previewVideo"
              controls
              crossorigin="anonymous"
              class="upload-video"
              @play="playVideo"
            >
              <source :src="tmpVideo!.url!" type="video/mp4" />
            </video>
          </div>
          <!-- <video ref="previewVideo" v-else controls crossorigin="anonymous" class="upload-video" @play="playVideo">
            <source :src="tmpVideo!.url!" type="video/mp4" />
          </video> -->
        </el-form-item>

        <el-form-item label="歌词" prop="lrc">
          <el-space direction="vertical" alignment="start" :size="10">
            <el-radio-group v-model="lrcType" class="ml-4">
              <el-radio :label="true" size="large">填写歌词</el-radio>
              <el-radio :label="false" size="large">上传LRC文件</el-radio>
            </el-radio-group>
            <el-upload
              v-if="!lrcType"
              ref="upload"
              class="ml-3"
              action=""
              :limit="1"
              :on-exceed="handleExceed"
              :auto-upload="false"
            >
              <template #trigger>
                <el-button type="primary">上传LRC</el-button>
              </template>
            </el-upload>
            <el-button
              v-else
              class="ml-3"
              type="success"
              @click="lrcDialog.visible = true"
            >
              填写歌词
            </el-button>
          </el-space>
        </el-form-item>

        <el-form-item label="标签" prop="genre">
          <el-select-v2
            v-model="formData.genre"
            filterable
            :options="cateOptions"
            placeholder="选择标签"
            style="width: 240px"
            :multiple="false"
          />
        </el-form-item>
        <el-form-item label="语言" prop="lang">
          <dictionary v-model="formData.lang" type-code="lang" />
        </el-form-item>
        <el-form-item label="介绍" prop="introduce">
          <el-input
            type="textarea"
            v-model="formData.introduce"
            placeholder="请输入歌手介绍"
            rows="6"
            autosize
          />
        </el-form-item>
        <el-form-item label="发行日期" prop="pushTime">
          <el-date-picker
            v-model="formData.pushTime"
            type="date"
            placeholder="选择发行日期"
          />
        </el-form-item>
        <el-form-item label="上架时间" prop="pushTime">
          <el-date-picker
            v-model="formData.pushTime"
            type="datetime"
            placeholder="选择上架时间"
          />
        </el-form-item>
        <el-form-item label="下架时间" prop="downTime">
          <el-date-picker
            v-model="formData.downTime"
            type="datetime"
            placeholder="选择下架时间"
          />
        </el-form-item>
        <el-form-item label="状态" prop="isActive">
          <el-switch v-model="formData.isActive" />
        </el-form-item>
        <el-form-item label="排序" prop="sort">
          <el-input-number
            v-model="formData.sort"
            style="width: 100px"
            controls-position="right"
            :min="0"
          />
        </el-form-item>
      </el-form>

      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">确 定</el-button>
          <el-button @click="closeDialog">取 消</el-button>
        </div>
      </template>
    </el-dialog>

    <!-- 音频文件转码弹窗 -->
    <el-dialog
      v-model="uploadDialog.visible"
      :title="uploadDialog.title"
      width="800px"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
      @close=""
      draggable
    >
      <el-card class="box-card">
        <template #header>
          <div class="card-header">
            <el-steps :active="active" align-center finish-status="success">
              <el-step title="准备" description="文件名称" />
              <el-step title="转码" description="转码状态" />
              <el-step title="上传" description="上传状态" />
            </el-steps>
          </div>
        </template>
        <el-table v-loading="loading" :data="tmpRateFileInfos" border>
          <el-table-column label="文件名称" prop="name" />
          <el-table-column label="音频质量" align="center">
            <template #default="scope">
              <el-tag v-if="scope.row.rate === '3000'" type="info">无损</el-tag>
              <el-tag v-else-if="scope.row.rate === '320'" type="info"
                >高质</el-tag
              >
              <el-tag v-else-if="scope.row.rate === '128'" type="info"
                >标准</el-tag
              >
              <el-tag
                v-else-if="scope.row.rate === '64' && !scope.row.isVip"
                type="info"
                >全损</el-tag
              >
              <el-tag v-else type="info">试听</el-tag>
            </template>
          </el-table-column>
          <el-table-column label="转码状态" align="center">
            <template #default="scope">
              <el-progress
                type="dashboard"
                :percentage="scope.row.transformProgress"
                :width="60"
              />
            </template>
          </el-table-column>
          <el-table-column label="上传状态" align="center">
            <template #default="scope">
              <el-progress
                type="dashboard"
                :percentage="scope.row.percentage"
                :width="60"
              />
            </template>
          </el-table-column>
          <el-table-column fixed="right" label="操作" align="center">
            <template #default="scope">
              <el-space spacer="|">
                <el-button
                  @click="play"
                  :disabled="active !== 3"
                  type="primary"
                  link
                  ><el-icon>
                    <VideoPlay /> </el-icon
                  >播放</el-button
                >
                <el-popconfirm
                  v-if="scope.$index === 0"
                  placement="right"
                  confirm-button-text="是"
                  cancel-button-text="否"
                  :icon="InfoFilled"
                  icon-color="#626AEF"
                  title="你确定要清空文件列表"
                  @confirm="confirmDelRateFiles"
                  @cancel="cancelDelPic"
                >
                  <template #reference>
                    <el-button type="primary" link
                      ><i-ep-delete />删除</el-button
                    >
                  </template>
                </el-popconfirm>
              </el-space>
            </template>
          </el-table-column>
        </el-table>
        <template #footer>
          <!-- <el-progress class="play-progress" color='#909399' :percentage="100" /> -->
          <audio
            ref="audio"
            @canplay="songCanplay"
            controls
            crossorigin="anonymous"
            :src="playSong?.path ?? ''"
          ></audio>
          <el-upload
            ref="upload"
            class="upload-demo"
            accept="audio/mp3,audio/webm,audio/3gpp,audio/3gpp2,audio/3gp2,audio/flac,audio/x-flac,audio/mpeg,audio/aac,audio/mpeg,audio/mp4,audio/ogg"
            action=""
            :limit="1"
            :on-exceed="handleExceed"
            :auto-upload="false"
            :on-change="audioFileChange"
          >
            <template #trigger>
              <el-button type="primary" :disabled="active && active !== 1"
                >选择音频文件</el-button
              >
            </template>
            <el-button
              :disabled="active !== 1"
              class="ml-3"
              type="success"
              @click="transformAudio"
            >
              转码
            </el-button>
            <el-button
              :disabled="active !== 2"
              class="ml-3"
              type="success"
              @click="submitUpload"
            >
              上传
            </el-button>
            <template #tip>
              <div class="el-upload__tip text-red">最多一个文件,否则会覆盖</div>
            </template>
          </el-upload>
        </template>
      </el-card>

      <template #footer>
        <div class="dialog-footer">
          <el-button
            type="primary"
            @click="handleAudioSubmit"
            :disabled="active && active !== 3"
            >确 定</el-button
          >
          <el-button @click="closeUploadDialog">取 消</el-button>
        </div>
      </template>
    </el-dialog>

    <!-- 填写歌词弹窗 -->
    <el-dialog
      v-model="lrcDialog.visible"
      :title="lrcDialog.title"
      width="800px"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
      @close=""
      draggable
    >
      <el-card class="box-card">
        <template #header>
          <div class="card-header">
            <el-steps align-center finish-status="success">
              <el-step title="载入音乐" />
              <el-step title="编辑歌词" />
              <el-step title="预览发布" />
            </el-steps>
          </div>
        </template>
        <el-form ref="queryFormRef" :model="queryParams" :inline="true">
          <el-row :gutter="24">
            <el-col :span="12">
              <el-form-item label="歌曲名" prop="pushTime">
                <el-input
                  v-model="lrcData.title"
                  placeholder="请输入歌曲名称"
                />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="歌手名" prop="pushTime">
                <el-input
                  v-model="lrcData.artist"
                  placeholder="请输入歌曲名称"
                />
              </el-form-item>
            </el-col>
          </el-row>
          <el-row :gutter="24">
            <el-col :span="12">
              <el-form-item label="专辑名" prop="downTime">
                <el-input
                  v-model="lrcData.album"
                  placeholder="请输入歌曲名称"
                />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="编辑人" prop="isActive">
                <el-input
                  v-model="lrcData.editor"
                  placeholder="请输入歌曲名称"
                />
              </el-form-item>
            </el-col>
          </el-row>
        </el-form>
        <LrcEditor></LrcEditor>
        <template #footer>
          <AudioPlayer></AudioPlayer>
          <el-input
            v-model="lrcData.audioUrl"
            placeholder="Please input"
            class="input-with-select"
          >
            <template #append>
              <el-upload
                class="flex"
                :limit="1"
                :auto-upload="false"
                :on-change="changeAudioFile"
                :show-file-list="false"
              >
                <template #trigger>
                  <el-button>上传音乐文件</el-button>
                </template>
              </el-upload>
            </template>
          </el-input>
        </template>
      </el-card>

      <template #footer>
        <div class="dialog-footer">
          <el-button
            type="primary"
            @click="handleLrcSubmit"
            :disabled="active && active !== 3"
            >确 定</el-button
          >
          <el-button @click="closeLrcDialog">取 消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<style scoped lang="scss">
.avatar {
  display: block;
  width: 178px;
  height: 178px;
  object-fit: scale-down;
}

.avatar-cover-wrapper {
  position: absolute;
  top: 0;
  left: 0;
  // cursor: default;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  // pointer-events: none;
  width: 100%;
  height: 100%;
  font-size: 20px;
  color: #fff;
  cursor: pointer;
  background-color: var(--el-overlay-color-lighter);
  opacity: 0;
  transition: opacity var(--el-transition-duration);

  .avatar-icon {
    font-size: 20px;
  }

  .avatar-zoomin-icon {
    margin-right: 15px;
  }
}

.avatar-delete-wrapper {
  position: relative;
  border: 1px dashed gray;

  &:hover {
    .avatar-cover-wrapper {
      opacity: 1;
    }
  }
}

.upload-video {
  // background-color: #000;
  position: relative;
  width: 500px;
  // height: 150px;
  aspect-ratio: 16 / 9;

  .upload-btn {
    width: 500px;
    height: 281.25px;
    aspect-ratio: 16 / 9;
  }
}

.delete-video-icon {
  position: absolute;
  top: 20px;
  right: 20px;
  z-index: 1000;
  color: #fff;
}

.el-upload {
  position: relative;
  overflow: hidden;
  cursor: pointer;
  border: 1px dashed var(--el-border-color);
  border-radius: 6px;
  transition: var(--el-transition-duration-fast);
}
</style>

<style lang="scss">
.play-progress {
  margin-bottom: 15px;
}

.avatar-uploader .el-upload {
  position: relative;
  overflow: hidden;
  cursor: pointer;
  border: 1px dashed var(--el-border-color);
  border-radius: 6px;
  transition: var(--el-transition-duration-fast);
}

.avatar-uploader .el-upload:hover {
  border-color: var(--el-color-primary);
}

.el-icon.avatar-uploader-icon {
  width: 178px;
  height: 178px;
  font-size: 28px;
  color: #8c939d;
  text-align: center;
}
</style>
